/* Copyright 2014-2018 Rsyn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once
#include <map>
#include <vector>

#include "Point.hh"
#include <string>

#include "astar.hh"
#include "builder.h"
#include "contest_db.h"
#include "def_service.h"
#include "flute3/flute.h"
#include "gridmap/gridmap.hh"
#include "lef_service.h"
#include "QuadraticTDP.h"

#include "api/TimingEngine.hh"
#include "api/TimingIDBAdapter.hh"








namespace ieda_contest {
class ContestDataManager;
class ContestInstance;
class QuadraticTDP;
struct GcellInstances
{
  std::vector<ContestInstance*> _instances;
  int _used_area;
  int _max_used_area;

  bool isViolation() {
    return _used_area > _max_used_area;
  }
};


// 坐标相对位置
enum class RelativeDirection {
    kUp,
    kDown,
    kLeft,
    kRight,
    kUp_left,
    kUp_right,
    kDown_left,
    kDown_right,
};

class AbuReduction
{
 public:
  AbuReduction() = delete;
  AbuReduction(ContestDataManager* data_manager, QuadraticTDP* quadraticTDP);
  AbuReduction(const AbuReduction&) = delete;
  AbuReduction(AbuReduction&&) = delete;
  ~AbuReduction() = default;

  AbuReduction& operator=(const AbuReduction&) = delete;
  AbuReduction& operator=(AbuReduction&&) = delete;

  // void computeABUVioaltionCells(const double alpha = 0);

  void runAbuReduction();

 private:
  ContestDataManager* _data_manager;
  QuadraticTDP* _qtdp;
  std::map<ContestCoord, GcellInstances> _gcell_instance_map;
  std::vector<std::tuple<ContestInstance*, std::tuple<double, ContestCoord>>> _abu_violation_cells;
  std::vector<std::tuple<ContestInstance*, std::tuple<float, int>>> clsABUViolationCells;

  int _max_gcell_id_x;
  int _max_gcell_id_y;
  int _core_max_x;
  int _core_max_y;

  bool _exit = 0;

  double _gcell_area_constraint;

  void moveABUViolationCells();
  void makeGCellInfo();
  void makeInstanceList();
  ContestCoord get_GCell_coord(const ContestCoord& coord);
  void findOverlap();
  std::tuple<ContestCoord, std::tuple<int, int>> findNearstNonviolationLocation(ContestInstance* contest_inst, ContestCoord gcell);
  std::vector<ContestCoord> getNeighbours(ContestCoord p, int radius);

  RelativeDirection whichDirection(ContestCoord a, ContestCoord b);

};  // end class

}  // namespace ieda_contest
